/*
 *  AParamClip.cpp
 *  libavid
 *
 *  Created by Peter on 29.02.12.
 *  Copyright 2012 __MyCompanyName__. All rights reserved.
 *
 */

#include "AParamClip.h"
#include "AStream.h"

A_IMPLEMENT_CLASS( 'PRCL', AParamClip, AClip );

void AParamClip::readFromStream( AStream& str, const AObjDoc& objd )
{
	AClip::readFromStream( str, objd );
	
	UInt8 tagMark, version;
	str.readPod( tagMark );
	str.readPod( version );
	TR_ASSERT( tagMark == 0x02 );
	TR_ASSERT( version == 0x01 );
	
	str.readPod( _interpKind );
	str.readPod( _valueType ); 
	TR_ASSERT( _valueType == 2 ); // Not sure what the contents is for other values
	
	Int32 numPts;
	str.readPod( numPts );
	TR_ASSERT( numPts >= 0 );
	
	// Remove any former nonsense. Potential memory leak for now, yay!!!
	_pts.clear();
	
	for( int i = 0; i < numPts; ++i ) {
		Pt* pt = new Pt; // Exception safety last, this could leak pt if any of the following code throws
		
		str.readPod( pt->_offsetNum );
		str.readPod( pt->_offsetDen );
		str.readPod( pt->_timeScale );
		str.readPod( pt->_valueDouble ); // I have a suspicion that if _valueType on the AParamClip object is set to a different value, this may be a different type
		
		Int16 numPps;
		str.readPod( numPps );
		TR_ASSERT( numPps >= 0 );
		
		for( int j = 0; j < numPps; ++j ) {
			PP pp;
			
			str.readPod( pp._ppCode );
			str.readPod( pp._ppType );
			
			switch( pp._ppType )
			{
				case PP_TYPE_DOUBLE:
					str.readPod( pp._value._ppFloat64 );
					break;
				case PP_TYPE_INTEGER:
					str.readPod( pp._value._ppInteger );
					break;
				default:
					throw "AParamClip: Unknown PP type";
			}
			
			pt->_pps.push_back( pp );
		}
		
		_pts.push_back( pt );
	}
	
	// PClass Ext ExtrapKind
	str.readPod( tagMark );
	str.readPod( version );
	
	// Encountered an old bin from V2.7 where this asserted. Types seemed to be
	// fine. Making a DomainData subsys Log for that file would obviously help.
	if( tagMark != 0x01 ) {
		TR_TRACE( "Ugs, aBout to assert..." );
		dump( std::clog );
	}
	TR_ASSERT( tagMark == 0x01 );
	TR_ASSERT( version == 0x01 );
	str.readPod( tagMark );
	TR_ASSERT( tagMark == 71 );
	
	str.readPod( _extrapKind );
	
	// PClass Ext Fields
	str.readPod( tagMark );
	str.readPod( version );
	TR_ASSERT( tagMark == 0x01 );
	TR_ASSERT( version == 0x02 );
	str.readPod( tagMark );
	TR_ASSERT( tagMark == 71 );
	
	str.readPod( _fields );
	
	// End TagMark
	str.readPod( tagMark );
	TR_ASSERT( tagMark == 0x03 );
}

#define TRACE_FIELD( x ) "\t" #x ": " << x << std::endl

void AParamClip::dump( std::ostream& str ) const
{
	str << "AParamClip {" << std::endl;
	
	str << "\t";
	AClip::dump( str );
	
	str << TRACE_FIELD( _interpKind );
	str << TRACE_FIELD( _valueType );
	
	str << "\t_pts[ " << _pts.size() << " ] {" << std::endl;
	
	PtList::const_iterator it = _pts.begin();
	for( int ptCounter = 0; it != _pts.end(); ++it, ++ptCounter )
	{
		str << "\t\tPt #" << ptCounter << " {" << std::endl;
		
		str << "\t\t\t_offsetNum: " << (*it)->_offsetNum << std::endl;
		str << "\t\t\t_offsetDen: " << (*it)->_offsetDen << std::endl;
		str << "\t\t\t_timeScale: " << (*it)->_timeScale << std::endl;
		str << "\t\t\t_valueDouble: " << (*it)->_valueDouble << std::endl;
		str << "\t\t\t_pps[ " << (*it)->_pps.size() << " ] {" << std::endl;
		
		PPList::const_iterator ppIt = (*it)->_pps.begin();
		for( ; ppIt != (*it)->_pps.end(); ++ppIt )
		{
			str << "\t\t\t\tPp {" << std::endl;
			
			str << "\t\t\t\t\t_ppCode: " << (*ppIt)._ppCode << std::endl;
			str << "\t\t\t\t\t_ppType: " << (*ppIt)._ppType << std::endl;
			
			switch( (*ppIt)._ppType )
			{
				case PP_TYPE_DOUBLE:
					str << "\t\t\t\t\t_value._ppFloat64: " << (*ppIt)._value._ppFloat64 << std::endl;
					break;

				case PP_TYPE_INTEGER:
					str << "\t\t\t\t\t_value._ppInteger: " << (*ppIt)._value._ppInteger << std::endl;
					break;
					
				default:
					str << "\t\t\t\t\t_value: <unsupported PPType>" << std::endl;
					break;
			}
					
			str << "\t\t\t\t}" << std::endl;
		}
		
		str << "\t\t\t}" << std::endl;
		
		str << "\t\t}" << std::endl;
	}
	
	str << "\t}" << std::endl;
	
	str << TRACE_FIELD( _extrapKind );
	str << TRACE_FIELD( _fields );
	
	str << "}" << std::endl;
}